import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.DataLine.Info;


public class SoundPlayer implements Runnable, IStreamSync{
    private SourceDataLine dataLine = null;
    private SoundFrame soundFrame;
    private SoundFile soundFile;
    private boolean playing = true;
    
    //private Object lockPlay = new Object();
    //private Object lockTime = new Object();
    
    public long getTimeStep(){
    	return soundFile.getTimeStep();
    }
   
   /* 
    private void printInfo(AudioFormat audioFormat){
    	System.out.println(audioFormat.getChannels());
    	System.out.println(audioFormat.getFrameRate());
    	System.out.println(audioFormat.getFrameSize());
    	System.out.println(audioFormat.getSampleRate());
    	System.out.println(audioFormat.getSampleSizeInBits());
    	System.out.println(audioFormat.getEncoding());
    }*/
    
    
    
    public SoundPlayer(String fileName){
    	soundFile = new SoundFile(fileName);
    	AudioFormat audioFormat = soundFile.getAudioFormat();
    	int frameSize = (int) (audioFormat.getFrameSize()* audioFormat.getFrameRate()/1000.0f*soundFile.getTimeStep());
    	//printInfo(audioFormat);
    	soundFrame = new SoundFrame(frameSize);

		Info info = new Info(SourceDataLine.class, audioFormat);
		
    	// opens the audio channel
		try {
		    dataLine = (SourceDataLine) AudioSystem.getLine(info);
		    dataLine.open(audioFormat, frameSize);
		} catch (LineUnavailableException e1) {
		    e1.printStackTrace();
		    dataLine.close();
		    return;
		}

		// Prepared to play audio stream
		dataLine.start();
    }
    
    public void playNextFrame() {
    	if(soundFile.ReadNextFrame(soundFrame))	{
    		dataLine.write(soundFrame.rawBuffer, 0, soundFrame.rawBuffer.length);
    	}
    	else {
    		// plays what's left and and closes the audioChannel
    		dataLine.drain();
    		dataLine.close();
    	}
    }

	@Override
	public void run() {
		while(true){
			//synchronized(lockPlay){
				if(playing){
					//synchronized(lockTime){
						playNextFrame();
					//}
				}
			//}
		}
	}

	@Override
	public void start() {
		// TODO Auto-generated method stub
		//synchronized(lockPlay){
			playing = true;
		//}
	}

	@Override
	public void pause() {
		// TODO Auto-generated method stub
		//synchronized(lockPlay){
			playing = false;
		//}
	}

	@Override
	public void stop() {
		// TODO Auto-generated method stub
		//synchronized(lockPlay){
			playing = false;
		//}
	}

	@Override
	public long getCurrentTimeStamp() {
		//synchronized(lockTime){
		// TODO Auto-generated method stub
			return soundFrame.timeStamp;
		//}
	}
}
